package city.spring.controller.mealService;

import city.spring.domain.entity.mealService.FoodInfoEntity;
import city.spring.domain.entity.mealService.MealTimeEntity;
import city.spring.domain.entity.mealService.RecipesWeekEntity;
import city.spring.domain.entity.mealService.WeekMealEntity;
import city.spring.modules.ext.entity.MealFoodExt;
import city.spring.modules.ext.service.MealFoodExtService;
import city.spring.service.mealService.FoodInfoService;
import city.spring.service.mealService.RecipesWeekService;
import city.spring.service.mealService.WeekMealService;
import city.spring.utils.MyBatisUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.api.ApiController;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;

@RestController
@RequestMapping("/week-meal")
public class WeekMealController extends ApiController {

    /**
     * <strong></strong> Service
     */
    private final WeekMealService weekMealService;
    private final FoodInfoService foodInfoService;
    private final RecipesWeekService recipesWeekService;
    private final MealFoodExtService mealFoodExtService;
    /**
     * 实体类（）可排序字段
     */
    private final List<SFunction<WeekMealEntity, ?>> entityOrderFields;
    private List<String> weekDayString = new LinkedList<>();
    private List<String> mealString = new LinkedList<>();

    public WeekMealController(WeekMealService weekMealService, FoodInfoService foodInfoService, RecipesWeekService recipesWeekService, MealFoodExtService mealFoodExtService) {
        this.weekMealService = weekMealService;
        this.foodInfoService = foodInfoService;
        this.recipesWeekService = recipesWeekService;
        this.mealFoodExtService = mealFoodExtService;
        weekDayString.add(0, "周一");
        weekDayString.add(1, "周二");
        weekDayString.add(2, "周三");
        weekDayString.add(3, "周四");
        weekDayString.add(4, "周五");
        weekDayString.add(5, "周六");
        weekDayString.add(6, "周日");
        this.entityOrderFields = new ArrayList<>();
        entityOrderFields.add(WeekMealEntity::getId);
        entityOrderFields.add(WeekMealEntity::getMealTime);
        entityOrderFields.add(WeekMealEntity::getMealDay);
        entityOrderFields.add(WeekMealEntity::getWeekId);
        entityOrderFields.add(WeekMealEntity::getGmtCreate);
        entityOrderFields.add(WeekMealEntity::getGmtModified);
    }

    /**
     * 获取全部的 <strong></strong> 列表
     */
    @GetMapping("all")
    public Object listAll(@PageableDefault(sort = {"mealDay"}) Pageable pageable, WeekMealEntity entity) {
        LambdaQueryChainWrapper<WeekMealEntity> lambdaQuery = buildLambdaQuery(entity);
        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
        return success(lambdaQuery.list());
    }

    /**
     * 分页获取 <strong></strong> 列表
     *
     * @param pageable 分页参数信息
     */
    @GetMapping
    public Object list(@PageableDefault(sort = {"mealDay"}) Pageable pageable, WeekMealEntity entity) {
        LambdaQueryChainWrapper<WeekMealEntity> lambdaQuery = buildLambdaQuery(entity);
        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
        Page<WeekMealEntity> page = lambdaQuery.page(MyBatisUtils.toPage(pageable, false));
        return success(page);
    }

    /**
     * 获取一个 <strong></strong>
     *
     * @param id 主键ID
     */
    @GetMapping("{id}")
    public Object info(@PathVariable String id) {
        WeekMealEntity entity = weekMealService.getById(id);
        RecipesWeekEntity recipesWeekEntity = recipesWeekService.getById(entity.getWeekId());
        recipesWeekService.loadMealTime(recipesWeekEntity);
        List<MealTimeEntity> mealTimeEntities = recipesWeekEntity.getMealTime();
        entity.setMealTimeString(mealTimeEntities.get(entity.getMealTime() - 1).getMealTime());
        Date dateStartTime = Date.from(recipesWeekEntity.getWeek().atStartOfDay(ZoneId.systemDefault()).toInstant());
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(dateStartTime);
        String year = (new SimpleDateFormat("yyyy")).format(dateStartTime);
        int week = calendar.get(Calendar.WEEK_OF_YEAR);
        String yearWeek = year + "年第" + week + "周";
        entity.setWeekIdString(yearWeek);
        entity.setMealDayString(weekDayString.get(entity.getMealDay() - 1));
        weekMealService.loadMealTurnFood(entity);
        return success(entity);
    }

    @GetMapping("/all-meal-turn/{id}")
    public Object getAllMealTurnFood(@PathVariable String id) {
        WeekMealEntity entity = weekMealService.getById(id);
        Map<String, List<FoodInfoEntity>> mealTurnFood = weekMealService.loadMealTurnFood(entity);
        return success(mealTurnFood);
    }

    @GetMapping("/votes-meal-turn/{id}")
    public Object getVotesMealTurnFood(@PathVariable String id) {
        WeekMealEntity entity = weekMealService.getById(id);
        Map<String, Map<Integer, List<FoodInfoEntity>>> votesMealTurnFood = weekMealService.loadVotesMealTurnFood(entity);
        return success(votesMealTurnFood);
    }

    @GetMapping("/meal-turn/{id}/{mealTurn}")
    public Object getMealTurnFood(@PathVariable String id, @PathVariable String mealTurn) {
        List<FoodInfoEntity> foodInfoEntities = foodInfoService.getMealTurnFood(id, mealTurn);
        return success(foodInfoEntities);
    }

    @GetMapping("/food/{id}")
    public Object getWeekMealFood(@PathVariable String id) {
        WeekMealEntity entity = weekMealService.getById(id);
        RecipesWeekEntity recipesWeekEntity = recipesWeekService.getById(entity.getWeekId());
        recipesWeekService.loadMealTime(recipesWeekEntity);
        LocalDate date = recipesWeekEntity.getStartTime().plusDays(entity.getMealDay() - 1);
        LocalTime startTime = recipesWeekEntity.getMealTime().get(entity.getMealTime() - 1).getStartTime();
        LocalTime endTime = recipesWeekEntity.getMealTime().get(entity.getMealTime() - 1).getEndTime();
        Map<String, List<FoodInfoEntity>> foodMap = weekMealService.currentFoodList(date, startTime, endTime);
        return success(foodMap);
    }

    /**
     * 添加一个 <strong></strong>
     *
     * @param entity 新增的信息
     */
    @PostMapping
    public Object add(@RequestBody WeekMealEntity entity) {
        weekMealService.save(entity);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.LOCATION, entity.getId());
        return new ResponseEntity<>(headers, HttpStatus.CREATED);
    }

    @PostMapping("/meal-turn/{id}/{mealTurn}")
    public Object addMealTurnFood(@PathVariable String id, @PathVariable String mealTurn, @RequestBody List<String> foodInfoEntitiesIds) {
        WeekMealEntity entity = weekMealService.getById(id);
        List<FoodInfoEntity> foodInfoEntities = new LinkedList<>();
        for (int i = 0; i < foodInfoEntitiesIds.size(); i++) {
            foodInfoEntities.add(i, foodInfoService.getById(foodInfoEntitiesIds.get(i)));
        }
        entity.setFoodInfoEntities(foodInfoEntities);
        weekMealService.setMealFood(entity, mealTurn);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.LOCATION, entity.getId());
        return new ResponseEntity<>(headers, HttpStatus.CREATED);
    }

    /**
     * 修改一个 <strong></strong>
     *
     * @param id     主键ID
     * @param entity 修改后的信息
     */
    @PutMapping("{id}")
    public Object update(@PathVariable String id, @RequestBody WeekMealEntity entity) {
        entity.setId(id);
        weekMealService.updateWeekMeal(entity);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PutMapping("/meal-turn/{id}/{mealTurn}")
    public Object updateMealTurnFood(@PathVariable String id, @PathVariable String mealTurn, @RequestBody List<String> foodInfoEntitiesIds) {
        WeekMealEntity entity = weekMealService.getById(id);
        List<FoodInfoEntity> foodInfoEntities = new LinkedList<>();
        for (int i = 0; i < foodInfoEntitiesIds.size(); i++) {
            foodInfoEntities.add(i, foodInfoService.getById(foodInfoEntitiesIds.get(i)));
        }
        entity.setFoodInfoEntities(foodInfoEntities);
        weekMealService.updateMealFood(entity, mealTurn);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.LOCATION, entity.getId());
        return new ResponseEntity<>(headers, HttpStatus.CREATED);
    }

    /**
     *
     */
    @PutMapping("/votes/{id}/{mealTurn}")
    public Object updateMealTurnVotes(@PathVariable String id, @PathVariable String mealTurn) {
        WeekMealEntity entity = weekMealService.getById(id);
        List<MealFoodExt> exts = mealFoodExtService.getMealFoodExt(entity.getId(), mealTurn);
        int votes = exts.get(0).getVotes() + 1;
        weekMealService.updateMealFoodVotes(entity, mealTurn, votes);
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.LOCATION, entity.getId());
        return new ResponseEntity<>(headers, HttpStatus.CREATED);
    }

    /**
     * 删除一个 <strong></strong>
     *
     * @param id 主键ID
     */
    @DeleteMapping("{id}")
    public Object delete(@PathVariable String id) {
        weekMealService.removeById(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @DeleteMapping("/meal-turn/{id}/{mealTurn}")
    public Object deleteMealTurnFood(@PathVariable String id, @PathVariable String mealTurn) {
        WeekMealEntity entity = weekMealService.getById(id);
        weekMealService.deleteMealFood(entity, mealTurn);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 删除多个 <strong></strong>
     *
     * @param ids 主键ID列表
     */
    @DeleteMapping
    public Object deleteIds(@RequestBody List<String> ids) {
        weekMealService.removeByIds(ids);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 构建查询条件内容
     *
     * @param entity 实体对象： <strong></strong>
     * @return lambda query chain wrapper
     */
    private LambdaQueryChainWrapper<WeekMealEntity> buildLambdaQuery(WeekMealEntity entity) {
        LambdaQueryChainWrapper<WeekMealEntity> lambdaQuery = weekMealService.lambdaQuery();
        lambdaQuery.eq(StringUtils.isNotBlank(entity.getId()), WeekMealEntity::getId, entity.getId());
        return lambdaQuery;
    }

}
